package com.ruitaowang.admin.other;

import com.alibaba.fastjson.JSON;
import com.baidu.ueditor.ActionEnter;
import com.ruitaowang.core.domain.FileUploadImage;
import com.ruitaowang.core.domain.Goods;
import com.ruitaowang.core.domain.GoodsAlbum;
import com.ruitaowang.core.utils.TimeUtils;
import com.ruitaowang.core.utils.aliyun.AliyunConfig;
import com.ruitaowang.core.utils.aliyun.OSSHelper;
import com.ruitaowang.core.web.BaseController;
import com.ruitaowang.core.web.MsgOut;
import com.ruitaowang.goods.dao.FileUploadImageMapper;
import com.ruitaowang.goods.service.GoodsService;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.apache.commons.fileupload.FileUploadException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.List;

/**
 * 上传
 */
@RestController
public class UploadController extends BaseController {

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private FileUploadImageMapper uploadImageMapper;
    @Value("${upload.voice}")
    private String voicePath;

    /**
     * 商品图片上传
     */

    @RequestMapping("/upload")
    public void upload(HttpServletRequest request, HttpServletResponse response, String isActivity) throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "text/html");
        String rootPath = getRequest().getSession().getServletContext().getRealPath("/");
        LOGGER.debug("UEditor 上传,rootPath:{}", rootPath);
        ActionEnter action = new ActionEnter(request, rootPath);
        String res = action.exec();
        GoodsAlbum goodsAlbum = JSON.parseObject(res, GoodsAlbum.class);
        Long goodsId = goodsAlbum.getGoodsId();
        if ("SUCCESS".equals(goodsAlbum.getState()) && StringUtils.isEmpty(isActivity)) {
            goodsService.insertAlbum(goodsAlbum);
            Goods goods = goodsService.selectByPK(goodsId);
            if (goodsAlbum.getImageType() == 1 && goods != null && StringUtils.isEmpty(goods.getGoodsThum())) {
                //设置默认封面
                goods = new Goods();
                goods.setGoodsId(goodsId);
                goods.setGoodsThum(goodsAlbum.getUrl());
                goodsService.update(goods);
            }
        }
        LOGGER.debug("UEditor 上传操作结果：{}", res);
        response.getWriter().print(res);
    }

    /**
     * 快转-图片 传送门
     */
    @RequestMapping("/image")
    public void uploadByRemoteUrl(String imageUrl, HttpServletResponse response) throws IOException {
        LOGGER.info("[file name] {}", imageUrl);
        if (!"undefined".equals(imageUrl)){
            try {
                OkHttpClient client = new OkHttpClient();
                //设置超时时间
//            client.setConnectTimeout(10, TimeUnit.SECONDS);
//            client.setWriteTimeout(10, TimeUnit.SECONDS);
//            client.setReadTimeout(30, TimeUnit.SECONDS);

//            Request request = new Request.Builder().url(imageUrl).build();
                okhttp3.Request request = new okhttp3.Request.Builder()
                        .url(imageUrl)
                        .build();
                Response resp = client.newCall(request).execute();
                OutputStream outputStream = response.getOutputStream();
                outputStream.write(resp.body().bytes());
                LOGGER.info("[resp] {}", resp);
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * base64格式的图片上传
     * @param base64Data
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/uploadImageForBase64", method = RequestMethod.POST)
    public String uploadImageForBase64(String base64Data) throws Exception {
        LOGGER.info("==上传图片==");
        String dataPrix = ""; //base64格式前头
        String data = "";//实体部分数据
        if(base64Data == null || "".equals(base64Data)){
            return this.renderJson(MsgOut.error("上传失败，上传图片数据为空"));
        }else {
            String [] d = base64Data.split("base64,");//将字符串分成数组
            if(d != null && d.length == 2){
                dataPrix = d[0];
                data = d[1];
            } else {
                return this.renderJson(MsgOut.error("上传失败，数据格式错误"));
            }
        }
        //Base64.Decoder decoder = Base64.getDecoder();
        Base64.Decoder decoder = Base64.getMimeDecoder();
        byte[] buffer = decoder.decode(data);
        //BASE64Decoder decoder = new BASE64Decoder();
        try {
            //byte[] buffer = decoder.decodeBuffer(data);
            for(int i = 0;i < buffer.length;++i) {
                if(buffer[i] < 0) {
                    //调整异常数据
                    buffer[i] += 256;
                }
            }
            String md5 = DigestUtils.md5DigestAsHex(buffer);
            FileUploadImage fileUploadImage = new FileUploadImage();
            fileUploadImage.setImageMd5(md5);
            fileUploadImage.setRemark("base64");
            FileUploadImage image = selectByMd5(fileUploadImage);
            if (!ObjectUtils.isEmpty(image)) {
                return this.renderJson(MsgOut.success(image.getImageUrl()));
            }
            String suffix = "";//图片后缀，用以识别哪种格式数据
            //编码的jpeg图片数据
            if("data:image/jpeg;".equalsIgnoreCase(dataPrix)){
                suffix = ".jpg";
            }else if("data:image/x-icon;".equalsIgnoreCase(dataPrix)){
                //编码的icon图片数据
                suffix = ".ico";
            }else if("data:image/gif;".equalsIgnoreCase(dataPrix)){
                //编码的gif图片数据
                suffix = ".gif";
            }else if("data:image/png;".equalsIgnoreCase(dataPrix)){
                //编码的png图片数据
                suffix = ".png";
            }else {
                return this.renderJson(MsgOut.error("上传失败，数据格式错误"));
            }
            String now = TimeUtils.getCurrentDatetime(TimeUtils.TimeFormat.SHORT_DATE_PATTERN_SLASH);
            String savePath = "attached/file/" + now + "/";
            String salt = TimeUtils.getCurrentDatetime(TimeUtils.TimeFormat.LONG_DATE_PATTERN_WITH_MILSEC_NONE_ORDER);
            String newFileName = savePath + salt + suffix;
            InputStream stream = new ByteArrayInputStream(buffer);
            OSSHelper.uploadToOSS(stream, newFileName);
            newFileName = AliyunConfig.staticHost + newFileName;
            LOGGER.info("newFileName == " + newFileName);
            insertImageForBase64(md5, newFileName, "base64");
            return this.renderJson(MsgOut.success(newFileName));
        } catch (IOException e) {
            e.printStackTrace();
            return this.renderJson(MsgOut.error("上传失败"));
        }
    }


    /**
     * 商家入住上传图片
     */
    @RequestMapping(value = "/uploadForCertificate", method = RequestMethod.POST)
    public String uploadForCertificate(@RequestParam("file") MultipartFile uploadfile) {//商家入住上传图片
        String newFileName = "", fileExt = "", fileName = uploadfile.getOriginalFilename();
        LOGGER.info("[file name] {}", fileName);
        try {
//            String now = TimeUtils.getCurrentDatetime(TimeUtils.TimeFormat.LONG_DATE_PATTERN_DD);
            String now = TimeUtils.getCurrentDatetime(TimeUtils.TimeFormat.SHORT_DATE_PATTERN_SLASH);
            String savePath = "attached/file/" + now + "/";
            InputStream stream = uploadfile.getInputStream();
            fileExt = ".jpg";
            if (fileName.lastIndexOf(".") != -1) {
                fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
            }

            //check file md5, if same file , return error.
            String md5 = DigestUtils.md5DigestAsHex(uploadfile.getBytes());
            FileUploadImage fileUploadImage = new FileUploadImage();
            fileUploadImage.setImageMd5(md5);
            FileUploadImage image = selectByMd5(fileUploadImage);
            if (!ObjectUtils.isEmpty(image)) {
                return this.renderJson(MsgOut.success(image.getImageUrl()));
            }

            //新文件名称
            String salt = TimeUtils.getCurrentDatetime(TimeUtils.TimeFormat.LONG_DATE_PATTERN_WITH_MILSEC_NONE_ORDER);
            newFileName = savePath + salt + fileExt;
            LOGGER.info("[newFileName] {}", newFileName);
            // Process the input stream
            //上传文件
            OSSHelper.uploadToOSS(stream, newFileName);
            stream.close();
            newFileName = AliyunConfig.staticHost + newFileName;
            //存储地址到数据库
            insertImage(md5, newFileName);

            return this.renderJson(MsgOut.success(newFileName));
        } catch (FileUploadException e) {
            e.printStackTrace();
            return this.renderJson(MsgOut.error("File upload error"));
        } catch (IOException e) {
            e.printStackTrace();
            return this.renderJson(MsgOut.error("Internal server IO error"));
        } catch (Exception e) {
            e.printStackTrace();
            return this.renderJson(MsgOut.error("File upload error"));
        }

    }
    /**
     * 将InputStream写入本地文件
     * @param destination 写入本地目录
     * @param input	输入流
     * @throws IOException
     */
    private static void writeToLocal(String destination, InputStream input)
            throws IOException {
        int index;
        byte[] bytes = new byte[1024];
        FileOutputStream downloadFile = new FileOutputStream(destination);
        while ((index = input.read(bytes)) != -1) {
            downloadFile.write(bytes, 0, index);
            downloadFile.flush();
        }
        downloadFile.close();
        input.close();
    }
    
    private FileUploadImage selectByMd5(FileUploadImage fileUploadImage) {
        List<FileUploadImage> fileUploadImages = uploadImageMapper.select(fileUploadImage);
        if (ObjectUtils.isEmpty(fileUploadImages)) {
            return null;
        }
        return fileUploadImages.get(0);
    }

    private void insertImage(String md5, String url) {
        FileUploadImage where = new FileUploadImage();
        where.setImageMd5(md5);
        where.setImageUrl(url);
        uploadImageMapper.insert(where);
    }

    private void insertImageForBase64(String md5, String url, String remark) {
        FileUploadImage where = new FileUploadImage();
        where.setImageMd5(md5);
        where.setImageUrl(url);
        where.setRemark(remark);
        uploadImageMapper.insert(where);
    }

    private void insertVideo(String md5, String url,String imgName) {
        FileUploadImage where = new FileUploadImage();
        where.setImageMd5(md5);
        where.setImageUrl(url);
        where.setRemark(imgName);
        uploadImageMapper.insert(where);
    }

    private void updateRemark(Long imageId,String imgName) {
        FileUploadImage where = new FileUploadImage();
        where.setImageId(imageId);
        where.setRemark(imgName);
        uploadImageMapper.updateByPK(where);
    }
}